home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / gnu / gnuchess.lha / nondsp.c < prev    next >
C/C++ Source or Header  |  1990-06-09  |  24KB  |  1,028 lines

  1. /*
  2.   nondsp.c - UNIX & MSDOS NON-DISPLAY, AND CHESSTOOL interface for Chess
  3.  
  4.   Revision: 1990-04-18
  5.  
  6.   Copyright (C) 1986, 1987, 1988, 1989, 1990 Free Software Foundation, Inc.
  7.   Copyright (c) 1988, 1989, 1990  John Stanback
  8.  
  9.   This file is part of CHESS.
  10.  
  11.   CHESS is distributed in the hope that it will be useful, but WITHOUT ANY
  12.   WARRANTY.  No author or distributor accepts responsibility to anyone for
  13.   the consequences of using it or for whether it serves any particular
  14.   purpose or works at all, unless he says so in writing.  Refer to the CHESS
  15.   General Public License for full details.
  16.  
  17.   Everyone is granted permission to copy, modify and redistribute CHESS, but
  18.   only under the conditions described in the CHESS General Public License.
  19.   A copy of this license is supposed to have been given to you along with
  20.   CHESS so you can know your rights and responsibilities.  It should be in a
  21.   file named COPYING.  Among other things, the copyright notice and this
  22.   notice must be preserved on all copies.
  23. */
  24.  
  25. #include <ctype.h>
  26. #include <signal.h>
  27. #ifdef MSDOS
  28. #include <dos.h>
  29. #include <conio.h>
  30. #include <stdlib.h>
  31. #include <string.h>
  32. #include <time.h>
  33. #else
  34. #include <sys/param.h>
  35. #include <sys/types.h>
  36. #include <sys/file.h>
  37. #include <sys/ioctl.h>
  38. void TerminateSearch (int), Die (int);
  39. #endif /* MSDOS */
  40.  
  41. #include "gnuchess.h"
  42.  
  43. #define pxx " PNBRQK"
  44. #define qxx " pnbrqk"
  45. #define rxx "12345678"
  46. #define cxx "abcdefgh"
  47. #define printz printf
  48. #define scanz scanf
  49.  
  50. static char mvstr[4][6];
  51. static char* ColorStr[2] = {"White", "Black"};
  52. static long evrate;
  53. static int mycnt1, mycnt2;
  54. static int ahead;
  55.  
  56. void
  57. Initialize (void)
  58. {
  59.   mycnt1 = mycnt2 = 0;
  60. #ifdef CHESSTOOL
  61.   setlinebuf (stdout);
  62.   /* setvbuf(stdout,NULL,_IOLBF,BUFSIZ); */
  63.   printf ("Chess\n");
  64.   if (Level == 0 && !TCflag)
  65.     Level = 15;
  66. #endif /* CHESSTOOL */
  67. }
  68.  
  69. void
  70. ExitChess (void)
  71. {
  72.   ListGame ();
  73.   exit (0);
  74. }
  75.  
  76. #ifndef MSDOS                /* never called!!! */
  77. void
  78. Die (int sig)
  79. {
  80.   char s[80];
  81.   ShowMessage ("Abort? ");
  82.   scanz ("%s", s);
  83.   if (strcmp (s, "yes") == 0)
  84.     ExitChess ();
  85. }
  86. #endif /* MSDOS */
  87.  
  88. void
  89. TerminateSearch (int sig)
  90. {
  91. #ifdef MSDOS
  92.   sig++;                /* shut up the compiler */
  93. #endif /* MSDOS */
  94.   flag.timeout = true;
  95.   flag.bothsides = false;
  96. }
  97.  
  98. void
  99. algbr (short int f, short int t, short int flag)
  100.                       
  101.  
  102. /*
  103.    Generate move strings in different formats.
  104. */
  105.  
  106. {
  107.   int m3p;
  108.  
  109.   if (f != t)
  110.     {
  111.       /* algebraic notation */
  112.       mvstr[0][0] = cxx[column (f)];
  113.       mvstr[0][1] = rxx[row (f)];
  114.       mvstr[0][2] = cxx[column (t)];
  115.       mvstr[0][3] = rxx[row (t)];
  116.       mvstr[0][4] = mvstr[3][0] = '\0';
  117.       if ((mvstr[1][0] = pxx[board[f]]) == 'P')
  118.     {
  119.       if (mvstr[0][0] == mvstr[0][2])    /* pawn did not eat */
  120.         {
  121.           mvstr[2][0] = mvstr[1][0] = mvstr[0][2];    /* to column */
  122.           mvstr[2][1] = mvstr[1][1] = mvstr[0][3];    /* to row */
  123.           m3p = 2;
  124.         }
  125.       else
  126.         /* pawn ate */
  127.         {
  128.           mvstr[2][0] = mvstr[1][0] = mvstr[0][0];    /* from column */
  129.           mvstr[2][1] = mvstr[1][1] = mvstr[0][2];    /* to column */
  130.           mvstr[2][2] = mvstr[0][3];
  131.           m3p = 3;        /* to row */
  132.         }
  133.       mvstr[2][m3p] = mvstr[1][2] = '\0';
  134.       if (flag & promote)
  135.         {
  136.           mvstr[0][4] = mvstr[1][2] = mvstr[2][m3p] = qxx[flag & pmask];
  137.           mvstr[1][3] = mvstr[2][m3p + 1] = mvstr[0][5] = '\0';
  138.         }
  139.     }
  140.       else
  141.     /* not a pawn */
  142.     {
  143.       mvstr[2][0] = mvstr[1][0];
  144.       mvstr[2][1] = mvstr[0][1];
  145.       mvstr[2][2] = mvstr[1][1] = mvstr[0][2];    /* to column */
  146.       mvstr[2][3] = mvstr[1][2] = mvstr[0][3];    /* to row */
  147.       mvstr[2][4] = mvstr[1][3] = '\0';
  148.       strcpy (mvstr[3], mvstr[2]);
  149.       mvstr[3][1] = mvstr[0][0];
  150.       if (flag & cstlmask)
  151.         {
  152.           if (t > f)
  153.         {
  154.           strcpy (mvstr[1], "o-o");
  155.           strcpy (mvstr[2], "O-O");
  156.         }
  157.           else
  158.         {
  159.           strcpy (mvstr[1], "o-o-o");
  160.           strcpy (mvstr[2], "O-O-O");
  161.         }
  162.         }
  163.     }
  164.     }
  165.   else
  166.     mvstr[0][0] = mvstr[1][0] = mvstr[2][0] = mvstr[3][0] = '\0';
  167. }
  168.  
  169.  
  170. int
  171. VerifyMove (char *s, short int iop, short unsigned int *mv)
  172.  
  173. /*
  174.    Compare the string 's' to the list of legal moves available for the
  175.    opponent. If a match is found, make the move on the board.
  176. */
  177.  
  178. {
  179.   static short pnt, tempb, tempc, tempsf, tempst, cnt;
  180.   static struct leaf xnode;
  181.   struct leaf *node;
  182.  
  183.   *mv = 0;
  184.   if (iop == 2)
  185.     {
  186.       UnmakeMove (opponent, &xnode, &tempb, &tempc, &tempsf, &tempst);
  187.       return (false);
  188.     }
  189.   cnt = 0;
  190.   MoveList (opponent, 2);
  191.   pnt = TrPnt[2];
  192.   while (pnt < TrPnt[3])
  193.     {
  194.       node = &Tree[pnt++];
  195.       algbr (node->f, node->t, (short) node->flags);
  196.       if (strcmp (s, mvstr[0]) == 0 || strcmp (s, mvstr[1]) == 0 ||
  197.       strcmp (s, mvstr[2]) == 0 || strcmp (s, mvstr[3]) == 0)
  198.     {
  199.       cnt++;
  200.       xnode = *node;
  201.     }
  202.     }
  203.   if (cnt == 1)
  204.     {
  205.       MakeMove (opponent, &xnode, &tempb, &tempc, &tempsf, &tempst, &INCscore);
  206.       if (SqAtakd (PieceList[opponent][0], computer))
  207.     {
  208.       UnmakeMove (opponent, &xnode, &tempb, &tempc, &tempsf, &tempst);
  209.       printz ("Illegal move\n");
  210.       return (false);
  211.     }
  212.       else
  213.     {
  214.       if (iop == 1)
  215.         return (true);
  216.       UpdateDisplay (xnode.f, xnode.t, 0, (short) xnode.flags);
  217.       if ((board[xnode.t] == pawn)
  218.           || (xnode.flags & capture)
  219.           || (xnode.flags & cstlmask))
  220.         {
  221.           Game50 = GameCnt;
  222.           ZeroRPT ();
  223.         }
  224.       GameList[GameCnt].depth = GameList[GameCnt].score = 0;
  225.       GameList[GameCnt].nodes = 0;
  226.       ElapsedTime (1);
  227.       GameList[GameCnt].time = (short) et;
  228.       TimeControl.clock[opponent] -= et;
  229.       --TimeControl.moves[opponent];
  230.       *mv = (xnode.f << 8) | xnode.t;
  231.       algbr (xnode.f, xnode.t, false);
  232.       return (true);
  233.     }
  234.     }
  235. #ifdef CHESSTOOL
  236.   printz ("Illegal move\n");
  237. #else
  238.   if (cnt > 1)
  239.     ShowMessage ("Ambiguous Move!");
  240. #endif
  241.   return (false);
  242. }
  243.  
  244. void
  245. help (void)
  246. {
  247.   ClrScreen ();
  248.   printz ("CHESS command summary\n");
  249.   printz ("----------------------------------------------------------------\n");
  250.   printz ("g1f3      move from g1 to f3      quit      Exit Chess\n");
  251.   printz ("Nf3       move knight to f3       beep      on/off\n");
  252.   printz ("o-o       castle king side        easy      on/off\n");
  253.   printz ("o-o-o     castle queen side       hash      on/off\n");
  254.   printz ("bd        redraw board            reverse   board display\n");
  255.   printz ("list      game to chess.lst       book      on/off\n");
  256.   printz ("undo      undo last ply           remove    take back a move\n");
  257.   printz ("edit      edit board              force     enter game moves\n");
  258.   printz ("switch    sides with computer     both      computer match\n");
  259.   printz ("white     computer plays white    black     computer plays black\n");
  260.   printz ("depth     set search depth        clock     set time control\n");
  261.   printz ("post      principle variation     hint      suggest a move\n");
  262.   printz ("save      game to file            get       game from file\n");
  263.   printz ("random    randomize play          new       start new game\n");
  264.   printz ("----------------------------------------------------------------\n");
  265.   printz ("Computer: %-12s Opponent:            %s\n",
  266.       ColorStr[computer], ColorStr[opponent]);
  267.   printz ("Depth:    %-12d Response time:       %d sec\n",
  268.       MaxSearchDepth, Level);
  269.   printz ("Random:   %-12s Easy mode:           %s\n",
  270.       (dither) ? "ON" : "OFF", (flag.easy) ? "ON" : "OFF");
  271.   printz ("Beep:     %-12s Transposition table: %s\n",
  272.       (flag.beep) ? "ON" : "OFF", (flag.hash) ? "ON" : "OFF");
  273.   signal (SIGINT, TerminateSearch);
  274. #ifndef MSDOS  
  275.   signal (SIGQUIT, TerminateSearch);
  276. #endif /* MSDOS */  
  277. }
  278.  
  279. void
  280. EditBoard (void)
  281. /*
  282.    Set up a board position. Pieces are entered by typing the piece followed
  283.    by the location. For example, Nf3 will place a knight on square f3.
  284. */
  285.  
  286. {
  287.   short a, r, c, sq, i;
  288.   char s[80];
  289.  
  290.   ClrScreen ();
  291.   UpdateDisplay (0, 0, 1, 0);
  292.   printz (".   exit to main\n");
  293.   printz ("#   clear board\n");
  294.   printz ("c   change sides\n");
  295.   printz ("enter piece & location: \n");
  296.  
  297.   a = white;
  298.   do
  299.     {
  300.       scanz ("%s", s);
  301.       if (s[0] == '#')
  302.     for(sq = 0; sq < 64; sq++)
  303.       {
  304.         board[sq] = no_piece;
  305.         color[sq] = neutral;
  306.       }
  307.       if (s[0] == 'c' || s[0] == 'C')
  308.     a = otherside[a];
  309.       c = s[1] - 'a';
  310.       r = s[2] - '1';
  311.       if ((c >= 0) && (c < 8) && (r >= 0) && (r < 8))
  312.     {
  313.       sq = locn (r, c);
  314.       color[sq] = a;
  315.        board[sq] = no_piece;
  316.        for(i = no_piece; i <= king; i++)
  317.          if ((s[0] == pxx[i]) || (s[0] == qxx[i]))
  318.            {
  319.              board[sq] = i;
  320.              break;
  321.            }
  322.     }
  323.   } while (s[0] != '.');
  324.   for (sq = 0; sq < 64; sq++)
  325.     Mvboard[sq] = (board[sq] != Stboard[sq]) ? 10 : 0;
  326.   GameCnt = 0;
  327.   Game50 = 1;
  328.   ZeroRPT ();
  329.   InitializeStats ();
  330.   ClrScreen ();
  331.   UpdateDisplay (0, 0, 1, 0);
  332. }
  333.  
  334. void
  335. SetupBoard (void)
  336.  
  337. /*
  338.    Compatibility with Unix chess and the nchesstool.
  339.    Set up a board position. Eight lines of eight characters are used
  340.    to setup the board. a8-h8 is the first line.
  341.    Black pieces are  represented  by  uppercase characters.
  342. */
  343.  
  344. {
  345.   short r, c, sq, i;
  346.   char ch;
  347.   char s[80];
  348.  
  349.   NewGame ();
  350.  
  351.   gets (s);            /* skip "setup" command */
  352.   for (r = 7; r >= 0; r--)
  353.     {
  354.       gets (s);
  355.       for (c = 0; c <= 7; c++)
  356.     {
  357.       ch = s[c];
  358.       sq = locn (r, c);
  359.       color[sq] = neutral;
  360.       board[sq] = no_piece;
  361.        for(i = no_piece; i <= king; i++)
  362.         if (ch == pxx[i])
  363.           {
  364.         color[sq] = black;
  365.         board[sq] = i;
  366.         break;
  367.           }
  368.         else
  369.           if (ch == qxx[i])
  370.         {
  371.           color[sq] = white;
  372.           board[sq] = i;
  373.           break;
  374.         }
  375.     }      
  376.     }
  377.   for (sq = 0; sq < 64; sq++)
  378.     Mvboard[sq] = (board[sq] != Stboard[sq]) ? 10 : 0;
  379.   InitializeStats ();
  380.   ClrScreen ();
  381.   UpdateDisplay (0, 0, 1, 0);
  382.   printz ("Setup successful\n");
  383. }
  384.  
  385. void
  386. ShowDepth (char ch)
  387. {
  388. #ifdef MSDOS
  389.   ch++;                    /* shut up the compiler */
  390. #endif /* MSDOS */
  391. }
  392.  
  393. void
  394. ShowResults (short int score, short unsigned int *bstline, char ch)
  395. {
  396.   register int i;
  397.   if (flag.post)
  398.     {
  399.       fprintf (stderr, "%2d%c %6d %4ld %8ld  ", Sdepth, ch, score, et, NodeCnt);
  400.       for (i = 1; bstline[i] > 0; i++)
  401.     {
  402.       if ((i > 1) && (i % 8 == 1))
  403.         fprintf (stderr, "\n                          ");
  404.       algbr ((short) (bstline[i] >> 8), (short) (bstline[i] & 0xFF), false);
  405.       fprintf (stderr, "%5s ", mvstr[0]);
  406.     }
  407.       fprintf (stderr, "\n");
  408.     }
  409. }
  410.  
  411. void
  412. SearchStartStuff (short int side)
  413. {
  414.   signal (SIGINT, TerminateSearch);
  415. #ifndef MSDOS  
  416.   signal (SIGQUIT, TerminateSearch);
  417. #endif /* MSDOS */  
  418.   if (flag.post)
  419.     {
  420.       fprintf (stderr, "\nMove# %d    Target= %ld    Clock: %ld\n",
  421.            TCmoves - TimeControl.moves[side] + 1,
  422.            ResponseTime, TimeControl.clock[side]);
  423.     }
  424. }
  425.  
  426. void
  427. OutputMove (void)
  428. {
  429.   printz ("%d. ... %s\n", ++mycnt1, mvstr[0]);
  430.   if (root->flags & draw)
  431.     {
  432.       printz ("Draw\n");
  433.       ExitChess ();
  434.     }
  435.   if (root->score == -9999)
  436.     {
  437.       printz ("%s\n", ColorStr[opponent]);
  438.       ExitChess ();
  439.     }
  440.   if (root->score == 9998)
  441.     {
  442.       printz ("%s\n", ColorStr[computer]);
  443.       ExitChess ();
  444.     }
  445.   if (flag.post)
  446.     {
  447.       fprintf (stderr, "Nodes= %ld  Eval= %ld  Rate= %ld  ",
  448.            NodeCnt, EvalNodes, evrate);
  449.       fprintf (stderr, "Hash/Coll= %ld/%ld\n",
  450.            HashCnt, HashCol);
  451.     }
  452.  
  453.   UpdateDisplay (root->f, root->t, 0, root->flags);
  454.   fprintf (stderr, "My move is: %s\n", mvstr[0]);
  455.   if (flag.beep)
  456.     printz ("%c", 7);
  457.  
  458.   if (root->flags & draw)
  459.     fprintf (stderr, "Drawn game!\n");
  460.   else if (root->score == -9999)
  461.     fprintf (stderr, "opponent mates!\n");
  462.   else if (root->score == 9998)
  463.     fprintf (stderr, "computer mates!\n");
  464.   else if (root->score < -9000)
  465.     fprintf (stderr, "opponent will soon mate!\n");
  466.   else if (root->score > 9000)
  467.     fprintf (stderr, "computer will soon mate!\n");
  468. }
  469.  
  470. void
  471. ElapsedTime (short int iop)
  472.                
  473.  
  474. /*
  475.    Determine the time that has passed since the search was started. If the
  476.    elapsed time exceeds the target (ResponseTime+ExtraTime) then set timeout
  477.    to true which will terminate the search.
  478. */
  479.  
  480. {
  481.   if (ahead)
  482.     {
  483. #ifndef MSDOS  
  484.       long nchar;
  485.       ioctl(0, FIONREAD, &nchar);
  486.       if (nchar)
  487. #else    
  488.       if (kbhit())
  489. #endif /* MSDOS */
  490.     {
  491.       flag.timeout = true;
  492.       flag.bothsides = false;
  493.     }
  494.     }
  495.   et = time ((long *) 0) - time0;
  496.   if (et < 0)
  497.     et = 0;
  498.   ETnodes += 50;
  499.   if (et > et0 || iop == 1)
  500.     {
  501.       if (et > ResponseTime + ExtraTime && Sdepth > 1)
  502.     flag.timeout = true;
  503.       et0 = et;
  504.       if (iop == 1)
  505.     {
  506.       time0 = time ((long *) 0);
  507.       et0 = 0;
  508.     }
  509.       if (et > 0)
  510.     /* evrate used to be Nodes / cputime I dont` know why */
  511.     evrate = NodeCnt / (et + ft);
  512.       else
  513.     evrate = 0;
  514.       ETnodes = NodeCnt + 50;
  515.     }
  516. }
  517.  
  518. void
  519. SetTimeControl (void)
  520. {
  521.   if (TCflag)
  522.     {
  523.       TimeControl.moves[white] = TimeControl.moves[black] = TCmoves;
  524.       TimeControl.clock[white] = TimeControl.clock[black] = 60L * TCminutes;
  525.     }
  526.   else
  527.     {
  528.       TimeControl.moves[white] = TimeControl.moves[black] = 0;
  529.       TimeControl.clock[white] = TimeControl.clock[black] = 0;
  530.       Level = 60L * TCminutes;
  531.     }
  532.   et = 0;
  533.   ElapsedTime (1);
  534. }
  535.  
  536. void
  537. ClrScreen (void)
  538. {
  539. #ifndef CHESSTOOL
  540.   printz ("\n");
  541. #endif
  542. }
  543.  
  544. void
  545. UpdateDisplay (short int f, short int t, short int redraw, short int isspec)
  546. {
  547. #ifndef CHESSTOOL
  548.   short r, c, l;
  549.   if (redraw)
  550.     {
  551.       printz ("\n");
  552.       for (r = 7; r >= 0; r--)
  553.     {
  554.       for (c = 0; c <= 7; c++)
  555.         {
  556.           if (flag.reverse)
  557.         l = locn (7 - r, 7 - c);
  558.           else
  559.         l = locn (r, c);
  560.           if (color[l] == neutral)
  561.         printz (" -");
  562.           else if (color[l] == white)
  563.         printz (" %c", qxx[board[l]]);
  564.           else
  565.         printz (" %c", pxx[board[l]]);
  566.         }
  567.       printz ("\n");
  568.     }
  569.       printz ("\n");
  570.     }
  571. #endif /* CHESSTOOL */
  572. #ifdef MSDOS
  573.   f++; t++; isspec++;            /* shut up the compiler */
  574. #endif /* MSDOS */
  575. }
  576.  
  577. void
  578. GetGame (void)
  579. {
  580.   FILE *fd;
  581.   char fname[256];
  582.   int c;
  583.   short sq;
  584.   unsigned short m;
  585.  
  586.   printz ("Enter file name: ");
  587.   scanz ("%s", fname);
  588.   if (fname[0] == '\0')
  589.     strcpy (fname, "chess.000");
  590.   if ((fd = fopen (fname, "r")) != NULL)
  591.     {
  592.       fscanf (fd, "%hd%hd%hd", &computer, &opponent, &Game50);
  593.       fscanf (fd, "%hd%hd", &castld[white], &castld[black]);
  594.       fscanf (fd, "%hd%hd", &TCflag, &OperatorTime);
  595.       fscanf (fd, "%ld%ld%hd%hd",
  596.           &TimeControl.clock[white], &TimeControl.clock[black],
  597.           &TimeControl.moves[white], &TimeControl.moves[black]);
  598.       for (sq = 0; sq < 64; sq++)
  599.     {
  600.       fscanf (fd, "%hd%hd", &m, &Mvboard[sq]);
  601.       board[sq] = (m >> 8);
  602.       color[sq] = (m & 0xFF);
  603.       if (color[sq] == 0)
  604.         color[sq] = neutral;
  605.       else
  606.         --color[sq];
  607.     }
  608.       GameCnt = 0;
  609.       c = '?';
  610.       while (c != EOF)
  611.     {
  612.       ++GameCnt;
  613.       c = fscanf (fd, "%hd%hd%hd%ld%hd%hd%hd", &GameList[GameCnt].gmove,
  614.               &GameList[GameCnt].score, &GameList[GameCnt].depth,
  615.               &GameList[GameCnt].nodes, &GameList[GameCnt].time,
  616.               &GameList[GameCnt].piece, &GameList[GameCnt].color);
  617.       if (GameList[GameCnt].color == 0)
  618.         GameList[GameCnt].color = neutral;
  619.       else
  620.         --GameList[GameCnt].color;
  621.     }
  622.       GameCnt--;
  623.       if (TimeControl.clock[white] > 0)
  624.     TCflag = true;
  625.       computer--;
  626.       opponent--;
  627.     }
  628.   fclose (fd);
  629.   InitializeStats ();
  630.   UpdateDisplay (0, 0, 1, 0);
  631.   Sdepth = 0;
  632. }
  633.  
  634. void
  635. SaveGame (void)
  636. {
  637.   FILE *fd;
  638.   char fname[256];
  639.   short sq, i, c;
  640.  
  641.   printz ("Enter file name: ");
  642.   scanz ("%s", fname);
  643.  
  644.   if (fname[0] == '\0')
  645.     strcpy (fname, "chess.000");
  646.   if ((fd = fopen (fname, "w")) != NULL)
  647.     {
  648.       fprintf (fd, "%d %d %d\n", computer + 1, opponent + 1, Game50);
  649.       fprintf (fd, "%d %d\n", castld[white], castld[black]);
  650.       fprintf (fd, "%d %d\n", TCflag, OperatorTime);
  651.       fprintf (fd, "%ld %ld %d %d\n",
  652.            TimeControl.clock[white], TimeControl.clock[black],
  653.            TimeControl.moves[white], TimeControl.moves[black]);
  654.       for (sq = 0; sq < 64; sq++)
  655.     {
  656.       if (color[sq] == neutral)
  657.         c = 0;
  658.       else
  659.         c = color[sq] + 1;
  660.       fprintf (fd, "%d %d\n", 256 * board[sq] + c, Mvboard[sq]);
  661.     }
  662.       for (i = 1; i <= GameCnt; i++)
  663.     {
  664.       if (GameList[i].color == neutral)
  665.         c = 0;
  666.       else
  667.         c = GameList[i].color + 1;
  668.       fprintf (fd, "%d %d %d %ld %d %d %d\n",
  669.            GameList[i].gmove, GameList[i].score, GameList[i].depth,
  670.            GameList[i].nodes, GameList[i].time,
  671.            GameList[i].piece, c);
  672.     }
  673.       fclose (fd);
  674.       printz ("Game saved on file: %s", fname);
  675.     }
  676.   else
  677.     printz ("Could not open file: %s", fname);
  678. }
  679.  
  680. void
  681. ListGame (void)
  682. {
  683.   FILE *fd;
  684.   short i, f, t;
  685.   fd = fopen ("chess.lst", "w");
  686.   fprintf (fd, "\n");
  687.   fprintf (fd, "       score  depth   nodes  time         ");
  688.   fprintf (fd, "       score  depth   nodes  time\n");
  689.   for (i = 1; i <= GameCnt; i++)
  690.     {
  691.       f = GameList[i].gmove >> 8;
  692.       t = (GameList[i].gmove & 0xFF);
  693.       algbr (f, t, false);
  694.       if ((i % 2) == 0)
  695.     fprintf (fd, "         ");
  696.       else
  697.     fprintf (fd, "\n");
  698.       fprintf (fd, "%5s  %5d     %2d %7ld %5d", mvstr[0],
  699.            GameList[i].score, GameList[i].depth,
  700.            GameList[i].nodes, GameList[i].time);
  701.     }
  702.   fprintf (fd, "\n\n");
  703.   fclose (fd);
  704. }
  705.  
  706. void
  707. Undo (void)
  708. /*
  709.    Undo the most recent half-move.
  710. */
  711.  
  712. {
  713.   short f, t;
  714.   f = GameList[GameCnt].gmove >> 8;
  715.   t = GameList[GameCnt].gmove & 0xFF;
  716.   if (board[t] == king && distance (t, f) > 1)
  717.     (void) castle (GameList[GameCnt].color, f, t, 2);
  718.   else
  719.     {
  720.       /* Check for promotion: */
  721.       if ((row (f) == 6 && row (t) == 7) || (row (f) == 1 && row (t) == 0))
  722.     {
  723.       int g, from = f;
  724.       for (g = GameCnt - 1; g > 0; g--)
  725.         if (GameList[g].gmove & 0xFF == from)
  726.           from = GameList[g].gmove >> 8;
  727.       if (row (from) == 1 || row (from) == 6)
  728.         board[t] = pawn;
  729.     }
  730.  
  731.       board[f] = board[t];
  732.       color[f] = color[t];
  733.       board[t] = GameList[GameCnt].piece;
  734.       color[t] = GameList[GameCnt].color;
  735.       if (color[t] != neutral)
  736.     Mvboard[t]--;
  737.       Mvboard[f]--;
  738.     }
  739.   if (TCflag)
  740.     ++TimeControl.moves[color[f]];
  741.   GameCnt--;
  742.   computer = otherside[computer];
  743.   opponent = otherside[opponent];
  744.   flag.mate = false;
  745.   Sdepth = 0;
  746.   UpdateDisplay (0, 0, 1, 0);
  747.   InitializeStats ();
  748. }
  749.  
  750. void
  751. ShowMessage (char *s)
  752. {
  753.   fprintf (stderr, "%s\n", s);
  754. }
  755.  
  756. void
  757. ShowSidetomove (void)
  758. {
  759. }
  760.  
  761. void
  762. PromptForMove (void)
  763. {
  764. #ifndef CHESSTOOL
  765.   printz ("\nYour move is? ");
  766. #endif /* CHESSTOOL */
  767. }
  768.  
  769.  
  770. void
  771. ShowCurrentMove (short int pnt, short int f, short int t)
  772. {
  773. #ifdef MSDOS
  774.   f++; t++; pnt++;            /* shut up the compiler */
  775. #endif /* MSDOS */
  776. }
  777.  
  778. void
  779. ChangeAlphaWindow (void)
  780. {
  781.   printz ("window: ");
  782.   scanz ("%hd", &Awindow);
  783. }
  784.  
  785. void
  786. ChangeBetaWindow (void)
  787. {
  788.   printz ("window: ");
  789.   scanz ("%hd", &Bwindow);
  790. }
  791.  
  792. void
  793. GiveHint (void)
  794. {
  795.   algbr ((short) (hint >> 8), (short) (hint & 0xFF), false);
  796.   fprintf (stderr, "Hint: %s\n", mvstr[0]);
  797. }
  798.  
  799. void
  800. SelectLevel (void)
  801. {
  802.   printz ("Enter #moves #minutes: ");
  803.   scanz ("%hd %hd", &TCmoves, &TCminutes);
  804.   printz ("Operator time= ");
  805.   scanz ("%hd", &OperatorTime);
  806.   TCflag = (TCmoves > 1);
  807.   SetTimeControl ();
  808. }
  809.  
  810. void
  811. ChangeSearchDepth (void)
  812. {
  813.   printz ("depth= ");
  814.   scanz ("%hd", &MaxSearchDepth);
  815. }
  816.  
  817. void
  818. SetContempt (void)
  819. {
  820.   printz ("contempt= ");
  821.   scanz ("%hd", &contempt);
  822. }
  823.  
  824. void
  825. ChangeXwindow (void)
  826. {
  827.   printz ("xwndw= ");
  828.   scanz ("%hd", &xwndw);
  829. }
  830.  
  831. void
  832. TestSpeed(void (*f) (short int side, short int ply))
  833. {
  834.   short i;
  835.   long cnt, rate, t1, t2;
  836.   
  837.   t1 = time (0);
  838.   for (i = 0; i < 10000; i++)
  839.     {
  840.       f (opponent, 2);
  841.     }
  842.   t2 = time (0);
  843.   cnt = 10000L * (TrPnt[3] - TrPnt[2]);
  844.   rate = cnt / (t2 - t1);
  845.   printz ("Nodes= %ld Nodes/sec= %ld\n", cnt, rate);
  846. }
  847.  
  848.  
  849. void
  850. InputCommand (void)
  851. /*
  852.    Process the users command. If easy mode is OFF (the computer is thinking
  853.    on opponents time) and the program is out of book, then make the 'hint'
  854.    move on the board and call SelectMove() to find a response. The user
  855.    terminates the search by entering ^C (quit siqnal) before entering a
  856.    command. If the opponent does not make the hint move, then set Sdepth to
  857.    zero.
  858. */
  859.  
  860. {
  861.   int i;
  862.   short ok, tmp;
  863.   unsigned short mv;
  864.   char s[80];
  865.  
  866.   ok = flag.quit = false;
  867.   player = opponent;
  868.   ft = 0;
  869.   if (hint > 0 && !flag.easy && Book == NULL)
  870.     {
  871.       fflush (stdout);
  872.       time0 = time ((long *) 0);
  873.       algbr ((short) hint >> 8, (short) hint & 0xFF, false);
  874.       strcpy (s, mvstr[0]);
  875.       tmp = epsquare;
  876.       if (flag.post)
  877.     GiveHint ();
  878.       if (VerifyMove (s, 1, &mv))
  879.     {
  880.       ahead = 1;
  881.       SelectMove (computer, 2);
  882.       VerifyMove (mvstr[0], 2, &mv);
  883.       if (Sdepth > 0)
  884.         Sdepth--;
  885.     }
  886.       ft = time ((long *) 0) - time0;
  887.       epsquare = tmp;
  888.     }
  889.   ahead = 0;
  890.   while (!(ok || flag.quit))
  891.     {
  892.       PromptForMove ();
  893.       i = scanz ("%s", s);
  894.       if (i == EOF || s[0] == 0)
  895.     ExitChess ();
  896.       player = opponent;
  897.       if (strcmp (s, "bd") == 0)
  898.     {
  899.       ClrScreen ();
  900.       UpdateDisplay (0, 0, 1, 0);
  901.     }
  902.       else if (strcmp (s, "alg") == 0) /* noop */ ;
  903.       else if ((strcmp (s, "quit") == 0) || (strcmp(s, "exit") == 0))
  904.     flag.quit = true;
  905.       else if (strcmp (s, "post") == 0)
  906.     flag.post = !flag.post;
  907.       else if ((strcmp (s, "set") == 0) || (strcmp(s, "edit") == 0))
  908.     EditBoard ();
  909.       else if (strcmp (s, "setup") == 0)
  910.     SetupBoard ();
  911.       else if (strcmp (s, "go") == 0)
  912.     ok = true;
  913.       else if (strcmp (s, "help") == 0)
  914.     help ();
  915.       else if (strcmp (s, "force") == 0)
  916.     flag.force = !flag.force;
  917.       else if (strcmp (s, "book") == 0)
  918.     Book = NULL;
  919.       else if (strcmp (s, "new") == 0)
  920.     NewGame ();
  921.       else if (strcmp (s, "list") == 0)
  922.     ListGame ();
  923.       else if (strcmp (s, "level") == 0 || strcmp (s, "clock") == 0)
  924.     SelectLevel ();
  925.       else if (strcmp (s, "hash") == 0)
  926.     flag.hash = !flag.hash;
  927.       else if (strcmp (s, "beep") == 0)
  928.     flag.beep = !flag.beep;
  929.       else if (strcmp (s, "Awindow") == 0)
  930.     ChangeAlphaWindow ();
  931.       else if (strcmp (s, "Bwindow") == 0)
  932.     ChangeBetaWindow ();
  933.       else if (strcmp (s, "rcptr") == 0)
  934.     flag.rcptr = !flag.rcptr;
  935.       else if (strcmp (s, "hint") == 0)
  936.     GiveHint ();
  937.       else if (strcmp (s, "both") == 0)
  938.     {
  939.       flag.bothsides = !flag.bothsides;
  940.       Sdepth = 0;
  941.       ElapsedTime (1);
  942.       SelectMove (opponent, 1);
  943.       ok = true;
  944.     }
  945.       else if (strcmp (s, "reverse") == 0)
  946.     {
  947.       flag.reverse = !flag.reverse;
  948.       ClrScreen ();
  949.       UpdateDisplay (0, 0, 1, 0);
  950.     }
  951.       else if (strcmp (s, "switch") == 0)
  952.     {
  953.       computer = otherside[computer];
  954.       opponent = otherside[opponent];
  955.       flag.force = false;
  956.       Sdepth = 0;
  957.       ok = true;
  958.     }
  959.       else if (strcmp (s, "white") == 0 || strcmp (s, "first") == 0)
  960.     {
  961.       computer = white;
  962.       opponent = black;
  963.       ok = true;
  964.       flag.force = false;
  965.       Sdepth = 0;
  966.     }
  967.       else if (strcmp (s, "black") == 0)
  968.     {
  969.       computer = black;
  970.       opponent = white;
  971.       ok = true;
  972.       flag.force = false;
  973.       Sdepth = 0;
  974.     }
  975.       else if (strcmp (s, "undo") == 0 && GameCnt > 0)
  976.     Undo ();
  977.       else if (strcmp (s, "remove") == 0 && GameCnt > 1)
  978.     {
  979.       Undo ();
  980.       Undo ();
  981.     }
  982.       else if (strcmp (s, "get") == 0)
  983.     GetGame ();
  984.       else if (strcmp (s, "save") == 0)
  985.     SaveGame ();
  986.       else if (strcmp (s, "depth") == 0)
  987.     ChangeSearchDepth ();
  988.       else if (strcmp (s, "random") == 0)
  989.     dither = 6;
  990.       else if (strcmp (s, "easy") == 0)
  991.     flag.easy = !flag.easy;
  992.       else if (strcmp (s, "contempt") == 0)
  993.     SetContempt ();
  994.       else if (strcmp (s, "xwndw") == 0)
  995.     ChangeXwindow ();
  996.       else if (strcmp (s, "test") == 0)
  997.     {
  998.           ShowMessage("Testing MoveList Speed");
  999.       TestSpeed (MoveList);
  1000.           ShowMessage("Testing CaptureList Speed");
  1001.       TestSpeed (CaptureList);
  1002.     }
  1003.       else
  1004.     {
  1005.       ok = VerifyMove (s, 0, &mv);
  1006.       if (ok && mv != hint)
  1007.         {
  1008.           Sdepth = 0;
  1009.           ft = 0;
  1010.         }
  1011.     }
  1012.     }
  1013.  
  1014.   ElapsedTime (1);
  1015.   if (flag.force)
  1016.     {
  1017.       computer = opponent;
  1018.       opponent = otherside[computer];
  1019.     }
  1020. #ifdef CHESSTOOL
  1021.   printf ("%d. %s\n", ++mycnt2, s);
  1022. #endif /* CHESSTOOL */
  1023.   signal (SIGINT, TerminateSearch);
  1024. #ifndef MSDOS  
  1025.   signal (SIGQUIT, TerminateSearch);
  1026. #endif /* MSDOS */  
  1027. }
  1028.